package org.jeecg.common.util.mail;

import cn.hutool.core.util.StrUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.activation.URLDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.io.File;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * 邮件发送工具类
 *
 * @author xc
 */
public class MailUtil {

    private static final Logger logger = LoggerFactory.getLogger(MailUtil.class);

    private static String smtp;
    private static String pop;
    private static String from;
    private static String username;
    private static String password;
    private MimeMessage mimeMsg;
    private Session session;
    private Properties props;
    private static Multipart mp;
    final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";

    /**
     * Constructor
     *
     * @param smtp 邮件发送服务器
     */
    public MailUtil(String smtp, String pop, String from, String username, String password) {
        MailUtil.smtp = smtp;
        MailUtil.pop = pop;
        MailUtil.from = from;
        MailUtil.username = username;
        MailUtil.password = password;
        this.setSmtpHost(smtp);
        this.createMimeMessage();
    }

    /**
     * 设置邮件发送服务器
     *
     * @param hostName String
     */
    public void setSmtpHost(String hostName) {
        logger.info("设置系统属性：mail.smtp.host = " + hostName);
        if (props == null)
            props = System.getProperties(); //获得系统属性对象
        props.put("mail.smtp.host", hostName); //设置SMTP主机
        props.setProperty("mail.smtp.port", "465");
        props.setProperty("mail.smtp.ssl.enable", "true");
        props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
        props.setProperty("mail.smtp.socketFactory.fallback", "false");
        props.setProperty("mail.smtp.socketFactory.port", "465");
    }


    /**
     * 创建MIME邮件对象
     *
     * @return
     */
    public boolean createMimeMessage() {
        try {
            logger.info("准备获取邮件会话对象！");
            session = Session.getDefaultInstance(props, new Authenticator(){
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }});   //获得邮件会话对象
        } catch (Exception e) {
            System.err.println("获取邮件会话对象时发生错误！" + e);
            return false;
        }

        logger.info("准备创建MIME邮件对象！");
        try {
            mimeMsg = new MimeMessage(session); //创建MIME邮件对象
            mp = new MimeMultipart();

            return true;
        } catch (Exception e) {
            System.err.println("创建MIME邮件对象失败！" + e.getMessage());
            return false;
        }
    }

    /**
     * 设置SMTP是否需要验证
     *
     * @param need
     */
    public void setNeedAuth(boolean need) {
        logger.info("设置smtp身份认证：mail.smtp.auth = " + need);
        if (props == null) props = System.getProperties();
        if (need) {
            props.put("mail.smtp.auth", "true");
        } else {
            props.put("mail.smtp.auth", "false");
        }
    }

    /**
     * 设置用户名和密码
     *
     * @param name
     * @param pass
     */
    public void setNamePass(String name, String pass) {
        username = name;
        password = pass;
    }

    /**
     * 设置邮件主题
     *
     * @param mailSubject
     * @return
     */
    public boolean setSubject(String mailSubject) {
        logger.info("设置邮件主题！");
        try {
            mimeMsg.setSubject(mailSubject);
            return true;
        } catch (Exception e) {
            System.err.println("设置邮件主题发生错误！");
            return false;
        }
    }

    /**
     * 设置邮件正文
     *
     * @param mailBody String
     */
    public boolean setBody(String mailBody) {
        try {
            BodyPart bp = new MimeBodyPart();
            bp.setContent("" + mailBody, "text/html;charset=GBK");
            mp.addBodyPart(bp);

            return true;
        } catch (Exception e) {
            System.err.println("设置邮件正文时发生错误！" + e);
            return false;
        }
    }

    /**
     * 添加附件
     *
     * @param filename String
     */
    public boolean addFileAffix(String filename) {

        logger.info("增加邮件附件：" + filename);
        try {
            BodyPart bp = new MimeBodyPart();
            FileDataSource fileds = new FileDataSource(filename);
            bp.setDataHandler(new DataHandler(fileds));
            bp.setFileName(fileds.getName());

            mp.addBodyPart(bp);

            return true;
        } catch (Exception e) {
            System.err.println("增加邮件附件：" + filename + "发生错误！" + e);
            return false;
        }
    }

    /**
     * 添加远程附件
     *
     * @param fileurl
     * @return
     */
    public boolean addremoteFile(String fileurl, String filename) {
        logger.info("增加邮件附件：" + fileurl);
        try {
            BodyPart bp = new MimeBodyPart();
            URL url = new URL(fileurl);
            URLDataSource fileds = new URLDataSource(url);
            bp.setDataHandler(new DataHandler(fileds));
            bp.setFileName(MimeUtility.encodeWord(filename));

            mp.addBodyPart(bp);

            return true;
        } catch (Exception e) {
            System.err.println("增加邮件附件：" + fileurl + "发生错误！" + e);
            return false;
        }
    }


    /**
     * 添加多个远程附件
     *
     * @param files
     * @return
     */
    public boolean addmoreremoteFile(String files) {

        try {
            JSONArray arr = JSONArray.fromObject(files);
            Iterator<?> iter = arr.iterator();
            while (iter.hasNext()) {
                JSONObject obj = (JSONObject) iter.next();
                String fileurl = obj.getString("fileurl");
                String filename = obj.getString("filename");
                BodyPart bp = new MimeBodyPart();
                URL url = new URL(fileurl);
                URLDataSource fileds = new URLDataSource(url);
                bp.setDataHandler(new DataHandler(fileds));
                bp.setFileName(MimeUtility.encodeWord(filename));

                mp.addBodyPart(bp);
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 添加多个附件 流
     *@auth xwd
     * @return
     */
    public boolean addmoreremoteFile(List<Map<String,Object>> list) {

        try {
            for(int i=0;i<list.size();i++){
                String filename = list.get(i).get("filename").toString();
                byte[] fileByte = (byte[]) list.get(i).get("fileByte");
                DataHandler dh = new DataHandler(new ByteArrayDataSource(fileByte,"application/octet-stream"));
                BodyPart bp = new MimeBodyPart();
                bp.setDataHandler(dh);
                bp.setFileName(MimeUtility.encodeWord(filename));
                mp.addBodyPart(bp);
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 设置发信人
     *
     * @param from String
     */
    public boolean setFrom(String from) {
        logger.info("设置发信人！");
        try {
            mimeMsg.setFrom(new InternetAddress(from)); //设置发信人
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 设置收信人
     *
     * @param to String
     */
    public boolean setTo(String to) {
        if (to == null) return false;
        try {
            mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 设置抄送人
     *
     * @param copyto String
     */
    public boolean setCopyTo(String copyto) {
        if (copyto == null) return false;
        try {
            mimeMsg.setRecipients(Message.RecipientType.CC, (Address[]) InternetAddress.parse(copyto));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 读取邮件
     *
     * @return
     */
    public static boolean receive() {
        Folder folder = null;
        Store store = null;
        try {
            Properties props = new Properties();
            props.put("mail.pop3.host", pop);
            Session session = Session.getDefaultInstance(props, null);
            store = session.getStore("pop3");
            store.connect(pop, username, password);
            folder = store.getFolder("INBOX");
            folder.open(Folder.READ_ONLY);
            Message message[] = folder.getMessages();

            for (int i = 0, n = message.length; i < n; i++) {
                System.out.println(i + ": " + message[i].getFrom()[0]
                        + "/t" + message[i].getSubject());
            }
            folder.close(false);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (store != null) {
                    store.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
                return false;
            }
        }

    }

    /**
     * 发送邮件
     */
    public boolean sendOut() {
        Transport transport = null;
        try {
            mimeMsg.setContent(mp);
            mimeMsg.saveChanges();
            System.out.println("正在发送邮件....");

            Session mailSession = Session.getInstance(props, null);
            transport = mailSession.getTransport("smtp");
            transport.connect((String) props.get("mail.smtp.host"), username, password);
            transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.TO));
            //transport.sendMessage(mimeMsg,mimeMsg.getRecipients(Message.RecipientType.CC));
            //transport.send(mimeMsg);

            logger.info("发送邮件成功！");

            return true;
        } catch (Exception e) {
            System.err.println("邮件发送失败！" + e);
            e.printStackTrace();
            return false;
        } finally {
            if (transport != null) {
                try {
                    transport.close();
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 普通邮件发送
     *
     * @param subject
     * @param touser
     * @param content
     * @return
     */
    public boolean sendmail(String subject, String touser, String content) {
        this.setNeedAuth(true);
        if (!this.setSubject(subject)) {
            return false;
        } else if (!this.setBody(content)) {
            return false;
        } else if (!this.setTo(touser)) {
            return false;
        } else if (!this.setFrom(from)) {
            return false;
        } else {
            this.setNamePass(username, password);
            return this.sendOut();
        }
    }


    public boolean sendmail(String subject, String touser, String content, String file) {
        if (StrUtil.isBlank(file)) {
            return this.sendmail(subject, touser, content);
        } else {
            this.setNeedAuth(true);
            if (!this.setSubject(subject)) {
                return false;
            } else if (!this.setBody(content)) {
                return false;
            } else if (!this.setTo(touser)) {
                return false;
            } else if (!this.setFrom(from)) {
                return false;
            } else {
                boolean b = this.addFileAffix(file);
                if (!b) {
                    logger.error(file + ":附件添加失败。。。");
                }

                this.setNamePass(username, password);
                if (!this.sendOut()) {
                    return false;
                } else {
                    try {
                        File f = new File(file);
                        if (f.exists()) {
                            f.delete();
                        }
                    } catch (Exception var7) {
                        var7.printStackTrace();
                    }

                    return true;
                }
            }
        }
    }

    public static void main(String[] a){
        //    MailUtil.sendmail("供应商","346588750@qq.com","hehe");
    }

}
